#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <QSpacerItem>
#include <QVBoxLayout>
#include <QHBoxLayout>

#include <QAction>
#include <QContextMenuEvent>



#include "mythread.h"

#include "GY_8507_Func.h"

#include "log_Gen.h"
#include "mainwindow.h"




// CustomButton 构造函数实现
CustomButton::CustomButton(const QString &text, QWidget *parent)
    : QPushButton(text, parent) {
}

// 自定义按钮的鼠标按下事件
void CustomButton::mousePressEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton)
    {
        // 左键单击
        //QMessageBox::information(this, "提示", "按钮被左键单击");
        emit send_loadAction();
    }
    else if (event->button() == Qt::RightButton)
    {
        // 右键单击  this指代该CustomButton对象
        emit customContextMenuRequested(this,event->pos()); // 触发右键菜单
    }

    // 调用基类的 mousePressEvent，确保按钮的正常行为
    QPushButton::mousePressEvent(event);
}


CustomLabel::CustomLabel(const QString &text, QWidget *parent)
    : QLabel(text,parent) {

}

void CustomLabel::mousePressEvent(QMouseEvent *event)
{


    if (event->button() == Qt::LeftButton)
    {
        // 处理左键点击事件
        emit send_disreset(this->property("lab_index").toInt());

    }
    else if (event->button() == Qt::RightButton)
    {
        // 处理右键点击事件
        emit send_showGui(this->property("lab_index").toInt());
    }
    // 调用基类的 mousePressEvent，确保Label的正常行为
    QLabel::mousePressEvent(event);
}

void CustomLabel::mouseReleaseEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton)
    {
        //qDebug() << "Left button released";
        // 处理左键释放事件
    }
    else if (event->button() == Qt::RightButton)
    {
        //qDebug() << "Right button released";
        // 处理右键释放事件
    }

    // 调用基类的 mousePressEvent，确保Label的正常行为
    QLabel::mousePressEvent(event);
}


MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{

    // 创建一个 QThread 对象
    QThread* subThread = new QThread;
    // 主线程中创建一个该类的对象
    Mythread* mytask = new Mythread;

    // 将对象移入线程
    mytask->moveToThread(subThread);
    // 启动线程，此时，任务没有真正启动

    // 参数 Qt::QueuedConnection 确保在不同的线程之间进行通信时，信号和槽的调用是安全的
    // on_Rev 任务通过sendChanel  信号触发
    connect(this,  &MainWindow::sendhChanel,  mytask,  &Mythread::on_Rev      ,Qt::QueuedConnection);
    connect(mytask, &Mythread::CAN_DAT,        this,  &MainWindow::on_CAN_DAT, Qt::QueuedConnection);
    subThread->start();

    make_top_gui(); // 创建顶层界面

    // 这里只设置一次，不在get_config2file调用
    // 否则每次重载时，窗口控件会出现变化

    main_hlayout->addSpacing(40);
    main_hlayout->addLayout(v1_layout);
    main_hlayout->addSpacing(40);  //设置v1 v2 间距
    main_hlayout->addLayout(v2_layout);
    main_hlayout->addSpacing(40);  //设置v1 v2 间距
    main_hlayout->addLayout(v3_layout);

    myQwidgt->show();

    logPath1 = QCoreApplication::applicationDirPath()+"/DEV";
    scan_configfile(logPath1);

    initCan_GY8507();

    m_port = new QSerialPort(this);
    connect(&QTIM_rx, &QTimer::timeout, this, &MainWindow::slot_update_rx_timer);
    connect(&QTIM_tx, &QTimer::timeout, this, &MainWindow::slot_update_tx_timer);
    connect(m_port, &QSerialPort::readyRead, this, &MainWindow::onSerialPortReadyRead);

    ui->setupUi(this);
}

MainWindow::~MainWindow()
{
    delete ui;

    // 析构函数里释放数组指针,防止内存泄露风险
    // 。。。。然而会造成关机时报错，可能是指针未创建
    //。。。。 所以暂不处理
#if 0
    delete *myLab_Name;
    delete *myLE_txt;
    delete *WRT_myLab_Name;
    delete *WRT_myLE_txt;
    delete *LAB_myLab_Name;
    delete *LAB_myLE_txt;

    delete  QLab_CANDEV;
    delete  QLab_CANDEV ;
    delete  QCom_CANDEV ;
    delete  QCom_CANCHsel;
    delete  QLab_BaudRate ;
    delete  QCom_Baud ;
    delete  QPbtn_OPDEV ;
    delete  QLab_Config ;
    delete  QPbtn_LoadConfig ;
    delete  QCom_Config ;

    delete myQwidgt;
    delete sub1Qwidgt;
    delete top_layout;
    delete top_hlayout;
    delete main_hlayout;
    delete v1_scrollArea;
    delete v2_scrollArea;
    delete v3_scrollArea;
    delete v1_layout;
    delete v2_layout;
    delete v3_layout;

    delete  ctrlDiplayer ;
    delete  pBtn_Last ;
    delete  pBtn_Next ;
    delete  mylab   ;
    delete  spinbox_Num ;
    delete  loglayout ;
    delete  QCom_log;
#endif

}


// 在QtextEdit 追加颜色文本
void MainWindow::appendTextWithColor(QTextEdit *textEdit, const QString &text, QColor color)
{
    // 获取当前文本光标
    QTextCursor cursor = textEdit->textCursor();

    // 移动光标到文档末尾
    // 防止鼠标交互时导致窗口日志信息错乱
    cursor.movePosition(QTextCursor::End);

    //创建文本格式对象
    QTextCharFormat format;
    format.setForeground(color);

    // 应用格式到光标位置
    cursor.mergeCharFormat(format);

    // 追加文本并分行,确保窗口缩放时，日志也能按行显示 模拟append效果
    cursor.insertText(text + "\r\n");
}



// 显示右键菜单
void MainWindow::showContextMenu(CustomButton *cBtn,const QPoint &pos)
{

    QMenu contextMenu(this);
    QAction *loadConfigAction = contextMenu.addAction("加载历史日志");
    QAction *loadAlarmEvent   = contextMenu.addAction("查看报警事件");
    QAction *openCanDebug     = contextMenu.addAction("打开CAN调试窗口");
    connect(loadConfigAction, &QAction::triggered, this, &MainWindow::showLog_DisCtrl);
    connect(loadAlarmEvent,   &QAction::triggered, this, &MainWindow::showAlarm_DisCtrl);
    connect(openCanDebug,     &QAction::triggered, this, &MainWindow::showCanDebug_DisCtrl);
    contextMenu.exec(cBtn->mapToGlobal(pos));
}

// 显示log控制窗口
void MainWindow::showLog_DisCtrl()
{

    Realtime_flag = 0;
    scan_logfile(logPath2);
    ctrlDiplayer->setWindowTitle("日志log控制窗口");
    spinbox_Num->setValue(indexPage);

    loglayout->addWidget(pBtn_Last);
    loglayout->addWidget(mylab);
    loglayout->addWidget(spinbox_Num);
    loglayout->addWidget(QCom_log);
    loglayout->addWidget(pBtn_Next);


    // 连接 currentTextChanged 信号到槽函数
    connect(QCom_log, &QComboBox::currentTextChanged, [this](const QString &text) {
        qDebug() << "当前选中的项文本变化为:" << text;
        // 可以在这里调用其他成员函数或者执行其他操作
        lastfilePtr = 0;
        filePtr     = 0;
        LenCode     = 0;
    });


    connect(pBtn_Last,&QPushButton::clicked,[&](){
        // 这里执行按钮逻辑
        filePtr = lastfilePtr - LenCode * indexPage ;
        if(filePtr < 0) filePtr = 0;
        on_LoadLog();
    });

    connect(pBtn_Next,&QPushButton::clicked,[&](){
        // 这里执行按钮逻辑
        filePtr = lastfilePtr + LenCode * (indexPage) ;
        on_LoadLog();
    });

    connect(spinbox_Num, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), [&](int value) {
        // 使用 this 指针来访问成员变量
        indexPage = value;
    });

    ctrlDiplayer->setLayout(loglayout);
    ctrlDiplayer->setFixedWidth(600);
    ctrlDiplayer->topLevelWidget();
    ctrlDiplayer->show();

}


// 显示报警窗口
void MainWindow::showAlarm_DisCtrl()
{
    on_HisEvent();
    myhistorytable->show();
#if 0
    scan_logfile(logPath2);
    ctrlDiplayer->setWindowTitle("日志log控制窗口");
    spinbox_Num->setValue(indexPage);

    loglayout->addWidget(pBtn_Last);
    loglayout->addWidget(mylab);
    loglayout->addWidget(spinbox_Num);
    loglayout->addWidget(QCom_log);
    loglayout->addWidget(pBtn_Next);


    // 连接 currentTextChanged 信号到槽函数
    connect(QCom_log, &QComboBox::currentTextChanged, [this](const QString &text) {
        qDebug() << "当前选中的项文本变化为:" << text;
        // 可以在这里调用其他成员函数或者执行其他操作
        lastfilePtr = 0;
        filePtr     = 0;
        LenCode     = 0;
    });


    connect(pBtn_Last,&QPushButton::clicked,[&](){
        // 这里执行按钮逻辑
        filePtr = lastfilePtr - LenCode * indexPage ;
        if(filePtr < 0) filePtr = 0;
        on_LoadLog();
    });

    connect(pBtn_Next,&QPushButton::clicked,[&](){
        // 这里执行按钮逻辑
        filePtr = lastfilePtr + LenCode * (indexPage) ;
        on_LoadLog();
    });

    connect(spinbox_Num, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), [&](int value) {
        // 使用 this 指针来访问成员变量
        indexPage = value;
    });

    ctrlDiplayer->setLayout(loglayout);
    ctrlDiplayer->setFixedWidth(500);
    ctrlDiplayer->topLevelWidget();
    ctrlDiplayer->show();
#endif
}


// 显示调试窗口
void MainWindow::showCanDebug_DisCtrl()
{

    qDebug()<<"showCAN";
    ctrlCanDebug->setWindowTitle("CAN调试");
    //ctrlCanDebug->resize(1024,768);

    le_SendID->setFixedWidth(120);
    le_SendByte0->setFixedWidth(70);
    le_SendByte1->setFixedWidth(70);
    le_SendByte2->setFixedWidth(70);
    le_SendByte3->setFixedWidth(70);
    le_SendByte4->setFixedWidth(70);
    le_SendByte5->setFixedWidth(70);
    le_SendByte6->setFixedWidth(70);
    le_SendByte7->setFixedWidth(70);

    CanDebug_layout->addWidget(LabSendTxt);
    CanDebug_layout->addWidget(le_SendID);
    CanDebug_layout->addWidget(LabDatTxt);
    CanDebug_layout->addWidget(le_SendByte0);
    CanDebug_layout->addWidget(le_SendByte1);
    CanDebug_layout->addWidget(le_SendByte2);
    CanDebug_layout->addWidget(le_SendByte3);
    CanDebug_layout->addWidget(le_SendByte4);
    CanDebug_layout->addWidget(le_SendByte5);
    CanDebug_layout->addWidget(le_SendByte6);
    CanDebug_layout->addWidget(le_SendByte7);
    CanDebug_layout->addWidget(pBtn_Send);

    QtextB_Recv->resize(800,600);
    // 设置只读 禁用光标
    QtextB_Recv->setReadOnly(true);
    QtextB_Recv->setTextInteractionFlags(Qt::TextSelectableByMouse|Qt::TextSelectableByKeyboard);
    CanDebugRecv_layout->addWidget(QtextB_Recv);


    // 连接 currentTextChanged 信号到槽函数
    connect(pBtn_Send, &QPushButton::clicked, [&]() {
        bool ok;
        uint32_t id = (le_SendID->text()).toInt(&ok,16);
        uint8_t   Dat[8];

        Dat[0] = (le_SendByte0->text()).toInt(&ok,16);
        Dat[1] = (le_SendByte1->text()).toInt(&ok,16);
        Dat[2] = (le_SendByte2->text()).toInt(&ok,16);
        Dat[3] = (le_SendByte3->text()).toInt(&ok,16);
        Dat[4] = (le_SendByte4->text()).toInt(&ok,16);
        Dat[5] = (le_SendByte5->text()).toInt(&ok,16);
        Dat[6] = (le_SendByte6->text()).toInt(&ok,16);
        Dat[7] = (le_SendByte7->text()).toInt(&ok,16);

        // Setp3 ZLG CAN发送数据
        if(g_DevType_ZLG1_GY2 == 1)
        {
          Can_Send_EX(myChannel_Handle,id,Dat);
        }
        else if(g_DevType_ZLG1_GY2 == 2)
        {
            Can_Send_EX_GY(id,Dat);
        }
    });

    ctrlCanDebug->setLayout(CanDebug_MainLayout);
    CanDebug_MainLayout->addLayout(CanDebug_layout);
    CanDebug_MainLayout->addLayout(CanDebugRecv_layout);

    ctrlCanDebug->topLevelWidget();
    ctrlCanDebug->show();

}



int16_t InitCan(DEVICE_HANDLE *Dev_H,CHANNEL_HANDLE *CH_H,uint8_t index,uint32_t baud )
{
    ZCAN_CHANNEL_INIT_CONFIG config;
    *Dev_H = ZCAN_OpenDevice(ZCAN_USBCAN2,0,0);
    qDebug()<<"**"<<*Dev_H ;
    if(*Dev_H != INVALID_DEVICE_HANDLE){
        config.can_type = 0;//CAN设备
        config.can.acc_code = 0;
        config.can.acc_mask = 0xFFFFFFFF;// 全部接收
        config.can.mode = 0;//正常模式
        *CH_H = ZCAN_InitCAN(*Dev_H,index,&config);
        if(*CH_H != INVALID_DEVICE_HANDLE){
            char path[50] = {0};
            char value[100] = {0};
            sprintf_s(path, "%d/baud_rate", index);
            sprintf_s(value, "%d", baud);
            if(ZCAN_SetValue(*Dev_H, path, value)==1){
                if(ZCAN_StartCAN(*CH_H) == STATUS_OK){
                    return  1; //启动CAN 成功
                }else{
                    return -4;//启动CAN通道失败
                }
            }else{
                return  -3;//设置波特率失败
            }
        }else{
            return  -2;//设备初始化失败
        }
    }else{
       return -1;// 设备打开失败
    }
}


 int32_t MainWindow:: initCan_GY8507()
{
     static uint16_t load_finish = 0;
     uint16_t reval = 0;

     if(load_finish == 0)
     {
         load_finish = 1;
         HMODULE hmod = LoadLibraryA("VCI_CAN.dll");
         if(hmod == NULL)
         {
             qDebug()<< "加载 VCI_CAN.dll 失败";
             return  -1;
         }

         // 获取函数地址
         VCI_OpenDevice = (sfunc3)GetProcAddress(hmod,"VCI_OpenDevice");
         VCI_CloseDevice = (sfunc2)GetProcAddress(hmod,"VCI_CloseDevice");
         VCI_InitCAN    = (sfunc4)GetProcAddress(hmod,"VCI_InitCAN");
         VCI_StartCAN   = (sfunc3)GetProcAddress(hmod,"VCI_StartCAN");
         VCI_Transmit   = (sfunc41)GetProcAddress(hmod,"VCI_Transmit");
         VCI_Receive   = (sfunc41)GetProcAddress(hmod,"VCI_Receive");

         if(VCI_OpenDevice == NULL)
         {
             qDebug()<<"获取 VCI_OpenDevice 地址失败";
             FreeLibrary(hmod);
             reval += 1;
         }

         if(VCI_CloseDevice == NULL)
         {
             qDebug()<<"获取 VCI_CloseDevice 地址失败";
             FreeLibrary(hmod);
             reval += 10;
         }

         if(VCI_InitCAN == NULL)
         {
             qDebug()<<"获取 VCI_InitCan 地址失败";
             FreeLibrary(hmod);
             reval += 100;
         }

         if(VCI_StartCAN == NULL)
         {
             qDebug()<<"获取 VCI_StartCan 地址失败";
             FreeLibrary(hmod);
             reval += 1000;
         }

         if(VCI_Transmit == NULL)
         {
             qDebug()<<"获取 VCI_Transmit 地址失败";
             FreeLibrary(hmod);
             reval += 10000;
         }

         if(VCI_Receive == NULL)
         {
             qDebug()<<"获取 VCI_Receive 地址失败";
              FreeLibrary(hmod);
             reval += 100000;
         }

         qDebug()<< ((reval == 0 )? "VCI_CAN.dll 加载成功！" : "VCI_CAN.dll 加载成功！") ;
     }
     return  reval;
}



void MainWindow::Can_Send_EX(DEVICE_HANDLE Channel,uint32_t id,uint8_t *Data)
{
    ZCAN_Transmit_Data frame;
    memset(&frame, 0, sizeof(frame));
    frame.frame.can_id = MAKE_CAN_ID(id, 1, 0, 0);
    frame.frame.can_dlc = 8;

    memcpy(frame.frame.data, Data, 8);
    if (ZCAN_Transmit(Channel, &frame, 1) != 1)
    {
       qDebug()<<"发送失败";
    }
    else
    {
        QString outTxt;
        Gen_Insert_LogFile(&outTxt,
                           logPath2,
                           frame.frame.can_id - 0x80000000,
                           frame.frame.data,
                           1);
       //QtextB_Recv->append(outTxt);
        appendTextWithColor(QtextB_Recv,outTxt,Qt::red);
    }
}

void  MainWindow::Can_Send_EX_GY(uint32_t id,uint8_t *Data)
{

    VCI_CAN_OBJ sendbuf[1];

    sendbuf->ExternFlag=1;
    sendbuf->DataLen=8;
    sendbuf->RemoteFlag=0;

    uint32_t tempID = id << 3;

    uint32_t CanId_byte1 = (tempID & 0x000000FF)<< 24;
    uint32_t CanId_byte2 = (tempID & 0x0000FF00)<< 8;
    uint32_t CanId_byte3 = (tempID & 0x00FF0000)>> 8;
    uint32_t CanId_byte4 = (tempID & 0xFF000000)>> 24;

    uint32_t CanId_last = CanId_byte1 + CanId_byte2 + CanId_byte3 + CanId_byte4;

    sendbuf->ID = CanId_last;

    memcpy(sendbuf->Data, Data, 8);

    int32_t flag = VCI_Transmit(DEV_USBCAN,0,0,sendbuf);
    if(flag!=1)
    {
        qDebug()<<"发送失败"<<flag;
    }
    else
    {
        QString outTxt;
        Gen_Insert_LogFile(&outTxt,
                           logPath2,
                           id,
                           Data,
                           1);
        //QtextB_Recv->append(outTxt);
        appendTextWithColor(QtextB_Recv,outTxt,Qt::red);
    }
}



void MainWindow::CAN_SEND(sValArry sVal,DEVICE_HANDLE Channel,uint32_t mydat)
{
    uint32_t id = 0;
    uint8_t Dat[8] = {0,0,0,0,0,0,0,0};

    id = sVal.frame_id;

    // Setp1 填充帧头
    Dat[0] = (sVal.header>>8) & 0xff;
    Dat[1] = sVal.header & 0xff;

    // Setp2 填充数据
    switch (sVal.data_len)
    {
    case 0x01:
         Dat[sVal.data_ptr] = mydat ;
        break;

    case 0x02:
         Dat[sVal.data_ptr] =   (mydat >> 8) & 0xff ;
         Dat[sVal.data_ptr+1] = mydat &0xff ;
        break;

    case 0x03:
        Dat[sVal.data_ptr] =   (mydat >> 16) & 0xff ;
        Dat[sVal.data_ptr+1] = (mydat >> 8) & 0xff ;
        Dat[sVal.data_ptr+2] = mydat & 0xff ;
        break;

    case 0x04:
        Dat[sVal.data_ptr] =   (mydat >> 24) & 0xff ;
        Dat[sVal.data_ptr+1] = (mydat >> 16) & 0xff ;
        Dat[sVal.data_ptr+2] = (mydat >> 8) & 0xff ;
        Dat[sVal.data_ptr+3] = mydat & 0xff ;
        break;

    default:
     break;
    }

    // Setp3 ZLG CAN发送数据
    if(g_DevType_ZLG1_GY2 == 1)
    {
      Can_Send_EX(Channel,id,Dat);
    }
    else if(g_DevType_ZLG1_GY2 == 2)
    {
        Can_Send_EX_GY(id,Dat);
    }
}


void MainWindow::get_config2file(QString Dis_filePath,QString Wrt_filePath ,QString Lab_FilePath)
{
    qDebug()<<Dis_filePath;

    ql_temp = parseJsonArray(readJsonArrayFromFile(Dis_filePath));
    Wrt_ql_temp = parseJsonArray(readJsonArrayFromFile(Wrt_filePath));
    Lab_ql_temp = parseJsonArray(readJsonArrayFromFile(Lab_FilePath));

    //每次重载都需要删除布局上的控件
    clear_layout(v1_layout);
    clear_layout(v2_layout);
    clear_layout(v3_layout);

    int cnt = 0;
    for (const sValArry &item : ql_temp)
    {
        // 新建一个水平布局h11，用于放置标签和输入框
        QHBoxLayout *h11_layout = new QHBoxLayout();

        // 新建标签，放入h11布局
        myLab_Name[cnt] = new CustomLabel(item.var_name);
        myLab_Name[cnt]->setStyleSheet("font: 12pt ;");

        myLab_Name[cnt]->setProperty("lab_index", cnt); //设置唯一索引值

        h11_layout->addWidget(myLab_Name[cnt]);
        // 此处可以设置间距
        h11_layout->addSpacing(0);
        // 新建输入框，放入h11布局
        myLE_txt[cnt] = new QLineEdit();

        myLE_txt[cnt]->setEnabled(false);
        myLE_txt[cnt]->setStyleSheet("font: 12pt ;");
        myLE_txt[cnt]->setAlignment(Qt::AlignRight|Qt::AlignVCenter);

        h11_layout->addWidget(myLE_txt[cnt]);
        connect(myLab_Name[cnt],&CustomLabel::send_disreset,
                this,&MainWindow::on_send_disreset);

        connect(myLab_Name[cnt],&CustomLabel::send_showGui,
                this,&MainWindow::on_send_GUI);

        v1_layout->addLayout(h11_layout);   
        cnt++;
    }

    cnt = 0;
    for (const sValArry &item : Wrt_ql_temp)
    {
        // 新建一个水平布局h11，用于放置标签和输入框
        QHBoxLayout *h21_layout = new QHBoxLayout();

        // 新建标签，放入h11布局
        WRT_myLab_Name[cnt] = new QLabel(item.var_name);
        WRT_myLab_Name[cnt]->setStyleSheet("font: 12pt ;");
        h21_layout->addWidget(WRT_myLab_Name[cnt]);
        // 此处可以设置间距
        h21_layout->addSpacing(0);
        // 新建输入框，放入h11布局
        WRT_myLE_txt[cnt] = new QLineEdit();
        WRT_myLE_txt[cnt]->setStyleSheet("font: 12pt ;");
        //WRT_myLE_txt[cnt]->setAlignment(Qt::AlignRight|Qt::AlignVCenter);
        // 为 QLineEdit 设置唯一标识符（如索引）
        WRT_myLE_txt[cnt]->setProperty("index", cnt);
        // 绑定回车事件槽函数

        connect(WRT_myLE_txt[cnt], &QLineEdit::returnPressed, this, &MainWindow::onLineEditReturnPressed);
        h21_layout->addWidget(WRT_myLE_txt[cnt]);
        v2_layout->addLayout(h21_layout);
        cnt++;
    }

    cnt = 0;
    for (const sValArry &item : Lab_ql_temp)
    {
        // 新建一个水平布局h11，用于放置标签和输入框
        QHBoxLayout *h31_layout = new QHBoxLayout();

        // 新建标签，放入h31布局
        LAB_myLab_Name[cnt] = new QLabel(item.var_name);
        LAB_myLab_Name[cnt]->setStyleSheet("font: 12pt ;");
        h31_layout->addWidget(LAB_myLab_Name[cnt]);
        // 此处可以设置间距
        h31_layout->addSpacing(0);
        // 新建输入框，放入h11布局
        LAB_myLE_txt[cnt] = new QLineEdit();

        QSize size_a;
        size_a.setWidth(30);
        size_a.setHeight(30);
        LAB_myLE_txt[cnt]->setMaximumSize(size_a);
        LAB_myLE_txt[cnt]->setEnabled(false); //font: 12pt "Arial";
        LAB_myLE_txt[cnt]->setStyleSheet("background-color: rgb(255, 255, 255);");
        h31_layout->addWidget(LAB_myLE_txt[cnt]);
        v3_layout->addLayout(h31_layout);
        cnt++;
    }

}

// 清除布局上控件，不删除控件本身
void MainWindow::clear_layout(QLayout *layout)
{
    if(!layout) return;

    // 遍历布局中的子项
    QLayoutItem *item;
    while( (item = layout->takeAt(0)) != nullptr )
    {
        // 如果是layout,调用 clear_layout 删除
        // 如果是Qwidget,调用 deleteLater 删除
        if(QWidget *widget =  item->widget())
        {
             delete  widget;
        }
        else if(QLayout *childlayout = item->layout())
        {
            clear_layout(childlayout);
        }
        delete  item;
    }

}

//  获得设备参数,打开设备时调用这个接口
void MainWindow::get_DevParm()
{

    if(QCom_CANCHsel->currentText() == "0")
    {
       g_Channal = 0;
    }
    else if (QCom_CANCHsel->currentText() == "1")
    {
       g_Channal = 1;
    }


    switch (QCom_Baud->currentIndex())
    {
        //50K
        case 0:  g_Baud =50000;     break;
        //100K
        case 1:  g_Baud =100000;    break;
        //125K
        case 2:  g_Baud =1250000;   break;
        //250K
        case 3:  g_Baud =250000;    break;
        //500K
        case 4:  g_Baud =500000;    break;
        //1000K
        case 5:  g_Baud =1000000;   break;
        default:break;
    }
}




// 响应回车事件，这里处理数据收发
void MainWindow::onLineEditReturnPressed()
{
    // 获取发送信号的 QLineEdit 对象
    QLineEdit *lineEdit = qobject_cast<QLineEdit*>(sender());
    if (lineEdit)
    {
        // 获取 QLineEdit 的文本
        QString text = lineEdit->text();
        // 获取唯一标识符（索引）
        int index = lineEdit->property("index").toInt();
        // 验证输入是否为有效数据
        bool isValidFloat = false;
        // 尝试将输入转换为浮点数
        double floatValue = text.toDouble(&isValidFloat);
        if(isValidFloat)
        {
            // 判断数据是否超出限制
            if(  (Wrt_ql_temp[index].up_Limt >= floatValue)
               &&(Wrt_ql_temp[index].dn_Limt <= floatValue) )
            {
                // 输入是有效的整数或浮点数
                floatValue = floatValue - Wrt_ql_temp[index].offset;
                // 显示/真实 = dis_real_coff
                floatValue = floatValue * Wrt_ql_temp[index].dis_real_coff;
                CAN_SEND(Wrt_ql_temp[index],myChannel_Handle,floatValue);
            }
            else
            {
                QString message = QString("输入数据超限，范围应为：%1~%2")
                                  .arg(QString::number(Wrt_ql_temp[index].dn_Limt, 'f', 1))
                                  .arg(QString::number(Wrt_ql_temp[index].up_Limt, 'f', 1));;
                QMessageBox::warning(this, "信息", message);
                lineEdit->clear();
            }
        }
        else
        {
            // 输入无效，显示错误信息
            qDebug() << "Invalid input at index:" << index << "with value:" << text;
            // 弹出错误提示框
            QMessageBox::warning(this, "信息", "请输入合法的数值：整数、小数");
            // 清空输入框
            lineEdit->clear();
        }
    }
}




void MainWindow::on_BTN_OpenDev()
{
   if(QCom_CANDEV->currentText() == "ZLG_USBCAN")
   {
        if(QPbtn_OPDEV->text()=="打开CAN设备")
        {
           get_DevParm();
           qDebug()<<"通道"<<g_Channal<<"波特率"<<g_Baud;
          int reVal = InitCan(&MyCan_Handle,&myChannel_Handle,g_Channal,g_Baud);
          if( STATUS_OK == reVal)
          {
             g_DevType_ZLG1_GY2 = 1;
             QPbtn_OPDEV->setText("关闭CAN设备");
             QPbtn_OPDEV->setStyleSheet("background-color: rgb(170, 0, 0);");
             emit sendhChanel(myChannel_Handle);
          }
          else
          {
              g_DevType_ZLG1_GY2 = 0;
              QPbtn_OPDEV->setText("打开CAN设备");
              QMessageBox::information(this,"信息","初始化设备失败"+QString::number(reVal));
          }
        }
        else if(QPbtn_OPDEV->text()=="关闭CAN设备")
        {

           if(ZCAN_CloseDevice(MyCan_Handle) == STATUS_OK)
           {
             g_DevType_ZLG1_GY2 = 0;
             QPbtn_OPDEV->setText("打开CAN设备");
             QPbtn_OPDEV->setStyleSheet("background-color: rgb(205, 205, 205);");
           }
           else
           {
              g_DevType_ZLG1_GY2 = 0;
              QPbtn_OPDEV->setText("打开CAN设备");
              QPbtn_OPDEV->setStyleSheet("background-color: rgb(205, 205, 205);");
              QMessageBox::information(this,"信息","关闭设备失败!");
           }
        }
   }
   else if(QCom_CANDEV->currentText() == "GY8507")
   {
       VCI_INIT_CONFIG InitInfo[1];
       uint16_t ErrCode = 0;
       InitInfo->kCanBaud = VCI_BaudConfig[QCom_Baud->currentIndex()][0];
       InitInfo->Timing0  = VCI_BaudConfig[QCom_Baud->currentIndex()][1];
       InitInfo->Timing1  = VCI_BaudConfig[QCom_Baud->currentIndex()][2];

       InitInfo->Filter=0;
       InitInfo->AccCode=0x80000008;
       InitInfo->AccMask=0xFFFFFFFF;
       InitInfo->Mode=0;
       InitInfo->CanRx_IER=1;

       if(QPbtn_OPDEV->text()=="打开CAN设备")
       {
           if(VCI_OpenDevice(DEV_USBCAN,0,0)!= 1)
           {
               qDebug()<<"打开CAN设备失败";
               ErrCode += 1 ;

           }

           if(VCI_InitCAN(DEV_USBCAN,0,0,InitInfo)!=1)
           {
               qDebug()<<"CAN 初始化失败";
               ErrCode += 10 ;
           }

          if(VCI_StartCAN(DEV_USBCAN,0, 0)!=1)
          {
              qDebug()<<"CAN 启动失败";
              ErrCode += 100 ;
          }

          if(ErrCode == 0)
          {
              g_DevType_ZLG1_GY2 = 2;
              QPbtn_OPDEV->setText("关闭CAN设备");
              QPbtn_OPDEV->setStyleSheet("background-color: rgb(170, 0, 0);");
              // 这里需要一个信号激活线程
              emit sendhChanel(myChannel_Handle);
          }


       }
       else if(QPbtn_OPDEV->text()=="关闭CAN设备")
       {
           if((VCI_CloseDevice(DEV_USBCAN,0)!=1))
           {
               g_DevType_ZLG1_GY2 = 0;
               QPbtn_OPDEV->setText("打开CAN设备");
               QPbtn_OPDEV->setStyleSheet("background-color: rgb(205, 205, 205);");
               QMessageBox::information(this,"信息","关闭设备失败!");
           }
           else
           {
               g_DevType_ZLG1_GY2 = 0;
               QPbtn_OPDEV->setText("打开CAN设备");
               QPbtn_OPDEV->setStyleSheet("background-color: rgb(205, 205, 205);");
           }

       }
   }
   else if(QCom_CANDEV->currentText() == "RS232/485")
   {
       if(QPbtn_OPDEV->text()=="打开CAN设备")
       {
           QString currText = QCom_CANCHsel->currentText();
           int index = currText.indexOf(" ");
           QString portName = currText.left(index);
           int baudRate = 0;
           switch(QCom_Baud->currentIndex())
           {
             case 0x00: baudRate = 2400;   break;
             case 0x01: baudRate = 4800;   break;
             case 0x02: baudRate = 9600;   break;
             case 0x03: baudRate = 19200;  break;
             case 0x04: baudRate = 115200; break;
             case 0x05: baudRate = 921600; break;
             default:   baudRate = 115200; break;
           }

           if (openSerialPort(portName, baudRate))
           {
               QPbtn_OPDEV->setText("关闭CAN设备");
              // QTIM_rx.start(5);
           }
           else
           {
               QMessageBox::critical(this, "错误", "无法打开串口");
           }
       }
       else if(QPbtn_OPDEV->text()=="关闭CAN设备")
       {

           closeSerialPort();
           QPbtn_OPDEV->setText("打开CAN设备");
           QTIM_rx.stop();
       }
   }
}

void MainWindow::on_BTN_LoadConfig()
{
    Realtime_flag = 1;
    QString  tempdir = QCom_Config->currentText() ;
    QString  filePath =  QCoreApplication::applicationDirPath()  + "/DEV/"  + tempdir  + "/Dis_Config.json";
    QString  filePath1 = QCoreApplication::applicationDirPath()  + "/DEV/"  + tempdir  + "/Wrt_Config.json";
    QString  filePath2 = QCoreApplication::applicationDirPath()  + "/DEV/"  + tempdir  + "/Lab_Config.json";

    logPath2 = logPath1 + "/" + QCom_Config->currentText() + "/log/";
    qDebug()<<"配置已载入" << logPath2;

    // 重新载入配置时清空日志文件指针位置
    lastfilePtr = 0;
    filePtr = 0;
    LenCode = 0;
    get_config2file(filePath,filePath1,filePath2);
}

void MainWindow::on_R_BTN_LoadConfig()
{
    qDebug()<<"on_R_BTN_LoadConfig";
}



// CAN数据显示到窗口
void MainWindow::showCanDat(ZCAN_Receive_Data CANData,uint16_t sciAddr,UINT8 *Byte,QList<sValArry> mylist,QString DataTime)
{

    static uint32_t alarm_dn_flag[60]={0};
    static uint32_t alarm_up_flag[60]={0};

    int  k = 0;
    uint32_t header = 0;
    uint32_t s32dat = 0;
    float    f32dat = 0.0;
    uint32_t bit_ptr = 0;
    uint16_t myptr = 0;  //起始位置

    bool b_Val = false;

    for (const sValArry &item : mylist)
    {

        if(item.sci_1Master2Slave == 0)
        {
          if(CANData.frame.can_id - 0x80000000 == item.frame_id)
            {
                    switch (item.header_len)
                    {
                      case 0x01:
                           header = (uint32_t)CANData.frame.data[item.header_ptr];
                        break;

                      case 0x02:
                           header = ( (uint32_t)CANData.frame.data[item.header_ptr] << 8 )
                                     + CANData.frame.data[item.header_ptr+1] ;
                        break;

                    default:break;
                    }

                    if(header == item.header)
                    {
                        switch (item.data_len)
                        {
                        case 0x01:
                             s32dat = (uint32_t)CANData.frame.data[item.data_ptr] ;
                            break;

                        case 0x02:
                             s32dat =  ((uint32_t)CANData.frame.data[item.data_ptr] << 8)
                                       + CANData.frame.data[item.data_ptr + 1 ] ;
                            break;

                        case 0x03:
                            s32dat =    ((uint32_t)CANData.frame.data[item.data_ptr] << 16)
                                      + ((uint32_t)CANData.frame.data[item.data_ptr+1] << 8)
                                      + CANData.frame.data[item.data_ptr + 2 ] ;
                            break;

                        case 0x04:
                            s32dat =    ((uint32_t)CANData.frame.data[item.data_ptr] << 24)
                                      + ((uint32_t)CANData.frame.data[item.data_ptr+1] << 16)
                                      + ((uint32_t)CANData.frame.data[item.data_ptr+2] << 8)
                                      + CANData.frame.data[item.data_ptr + 3 ] ;
                            break;

                        default: break;
                        }

                        // 位数据处理
                        if(item.data_type>= 10)
                        {

                            bit_ptr = item.data_type - 10;
                            b_Val = GET_BIT(CANData.frame.data[item.data_ptr],bit_ptr);
                            if((enWindDispalyMode == WIND_LOG_PALY)
                              ||(enWindDispalyMode == WIND_REALY_TIME))
                            {
                                if(b_Val == true)
                                {
                                   LAB_myLE_txt[k]->setStyleSheet("background-color: rgb(170, 0, 0);");
                                }
                                else
                                {
                                   LAB_myLE_txt[k]->setStyleSheet("background-color: rgb(205, 205, 205);");
                                }
                            }

                        }
                        // 仅对有效数据长度1~4字节数据进行处理
                        else if( (item.data_len<= 4) && (item.data_len>= 1) )
                        {
                            s32dat = s32dat - item.offset;
                            f32dat =(float) s32dat / item.dis_real_coff;

                            // 数据在编辑框内显示
                            if((enWindDispalyMode == WIND_LOG_PALY)
                              ||(enWindDispalyMode == WIND_REALY_TIME))
                            {
                                myLE_txt[k]->setText(QString::number(f32dat,'f',item.data_type));
                            }
                        }

                        // 判断值是否超限
                        if(f32dat > item.up_Limt) //红 255 85 0
                        {
                            if(item.data_type>= 10)
                            {
                                LAB_myLE_txt[k]->setStyleSheet(
                                                           "font: 12pt; "
                                                           "color: rgb(255, 85, 0);"
                                                           );

                            }
                            else
                            {
                                myLE_txt[k]->setStyleSheet(
                                                           "font: 12pt; "
                                                           "color: rgb(255, 85, 0);"
                                                           );
                            }

                            if( (enWindDispalyMode == WIND_HISTORY_EVENT)
                                &&(Realtime_flag == 0) )
                            {
                                if(alarm_up_flag[k] == 0)
                                {
                                    alarm_up_flag[k] = 1;
                                    QString eventTxt = item.var_name + "上限报警："
                                                     + QString("%1").arg(f32dat, 0, 'f', 2);
                                    myhistorytable->addEvent(k,DataTime,eventTxt,1);
                                }
                            }
                        }
                        else if(f32dat < item.dn_Limt)// 蓝 0 0 255
                        {
                            if(item.data_type>= 10)
                            {
                                LAB_myLE_txt[k]->setStyleSheet(
                                                           "font: 12pt; "
                                                           "color: rgb(0, 0, 255);"
                                                           );
                            }
                            else
                            {
                                myLE_txt[k]->setStyleSheet(
                                                           "font: 12pt; "
                                                           "color: rgb(0, 0, 255);"
                                                           );
                            }
                            if( (enWindDispalyMode == WIND_HISTORY_EVENT)
                                &&(Realtime_flag == 0) )
                            {
                                if(alarm_dn_flag[k] == 0)
                                {
                                    alarm_dn_flag[k] = 1;
                                    QString eventTxt = item.var_name + "下限报警："
                                                             + QString("%1").arg(f32dat, 0, 'f', 2);
                                    myhistorytable->addEvent(k,DataTime,eventTxt,1);
                                }
                            }
                        }
                        else
                        {
                            if(item.data_type>= 10)
                            {
                                LAB_myLE_txt[k]->setStyleSheet("font: 12pt; "
                                                           "color: rgb(0, 0, 0);"
                                                           );
                            }
                            else
                            {
                                myLE_txt[k]->setStyleSheet("font: 12pt; "
                                                           "color: rgb(0, 0, 0);"
                                                           );
                            }

                            if(   (enWindDispalyMode == WIND_HISTORY_EVENT)
                                &&(Realtime_flag == 0)    )
                            {
                                if(alarm_up_flag[k] == 1)
                                {
                                    alarm_up_flag[k] = 0;
                                    QString eventTxt = item.var_name + "上限报警恢复："
                                            + QString("%1").arg(f32dat, 0, 'f', 2);
                                    myhistorytable->addEvent(k,DataTime,eventTxt,2);
                                }

                                if(alarm_dn_flag[k] == 1)
                                {
                                    alarm_dn_flag[k] = 0;
                                    QString eventTxt = item.var_name + "下限报警恢复："
                                            + QString("%1").arg(f32dat, 0, 'f', 2);

                                    myhistorytable->addEvent(k,DataTime,eventTxt,2);
                                }
                            }
                        }

                    }
                }
        }
        else if(item.sci_1Master2Slave == 1)
        {
            if(item.sci_Addr >= sciAddr)
            {
                myptr = (item.sci_Addr-sciAddr) * 2 + 3;
                qDebug()<<myptr;

                if(item.sci_Data_Type>= 10)
                {

                    bit_ptr = item.sci_Data_Type - 10;
                    b_Val = GET_BIT(Byte[myptr],bit_ptr);
                    if((enWindDispalyMode == WIND_LOG_PALY)
                      ||(enWindDispalyMode == WIND_REALY_TIME))
                    {
                        if(b_Val == true)
                        {
                           LAB_myLE_txt[k]->setStyleSheet("background-color: rgb(170, 0, 0);");
                        }
                        else
                        {
                           LAB_myLE_txt[k]->setStyleSheet("background-color: rgb(205, 205, 205);");
                        }
                    }
                }

                switch (item.sci_Data_Type)
                {
                    case 0x01:
                         s32dat = (uint32_t)Byte[myptr] ;
                        break;

                    case 0x02:
                         s32dat =  ((uint32_t)Byte[myptr]<< 8)
                                  +(uint32_t)Byte[myptr+1];
                        break;

                    case 0x03:
                        s32dat =    ( (uint32_t)Byte[myptr] << 16)
                                  + ( (uint32_t)Byte[myptr+1]<< 8)
                                  +   (uint32_t)Byte[myptr+2];
                        break;

                    case 0x04:
                        s32dat =    ( (uint32_t)Byte[myptr]  << 24)
                                  + ((uint32_t)Byte[myptr+1]  << 16)
                                  + ((uint32_t)Byte[myptr+2]  << 8)
                                  + (uint32_t)Byte[myptr+3]  ;
                        break;

                    default: break;
                }

            }
        }
        k++;
     }
 }


void MainWindow::on_CAN_DAT(ZCAN_Receive_Data *CANData, int num)
{
    int i=0;
    for(i = 0;i<num;i++)
    {
#if 0  //调试语句
      qDebug() << QString::number(CANData[i].frame.can_id,16)  \
               << QString::number(CANData[i].frame.data[0],16) \
               << QString::number(CANData[i].frame.data[1],16) \
               << QString::number(CANData[i].frame.data[2],16) \
               << QString::number(CANData[i].frame.data[3],16) \
               << QString::number(CANData[i].frame.data[4],16) \
               << QString::number(CANData[i].frame.data[5],16) \
               << QString::number(CANData[i].frame.data[6],16) \
               << QString::number(CANData[i].frame.data[7],16) ;
#endif
        QString outTxt;
        Gen_Insert_LogFile(&outTxt,
                           logPath2,
                           CANData[i].frame.can_id - 0x80000000,
                           CANData[i].frame.data,
                           0);
        //QtextB_Recv->append(outTxt);
        appendTextWithColor(QtextB_Recv,outTxt,Qt::blue);

       if(Realtime_flag == 1)
       {
         showCanDat(CANData[i],0,nullptr,ql_temp,nullptr);
         showCanDat(CANData[i],0,nullptr,Lab_ql_temp,nullptr);
       }
    }
}

// 加载日志
void MainWindow::on_LoadLog()
{
    QString textLine[1];
    S_LogEntry myVal;
    lastfilePtr = filePtr;
    logFileFullPath = logPath2 + QCom_log->currentText();
    Read_Loginfo_fromFile(logFileFullPath,textLine,1,&filePtr);
    LenCode = filePtr - lastfilePtr;

    bool isDat = parseLogLine(textLine[0], myVal);
    if (isDat)
    {
#if 0  //调试语句
        qDebug() << "Timestamp:" << myVal.timestamp.toString("yyyy-MM-dd HH:mm:ss.zzz")
        qDebug() << "Frame ID:" << myVal.frameId;
        qDebug() << "Frame Format:" << (myVal.frameFormat == 1 ? "数据帧" : "远程帧");
        qDebug() << "Is Extended Frame:" << myVal.isExtendedFrame;
        qDebug() << "Data Timestamp:" << myVal.dataTimestamp.toString("HH:mm:ss.zzz");
        qDebug() << "Data:" << QString::number(myVal.data[0],16)
                            << QString::number(myVal.data[1],16)
                            << QString::number(myVal.data[2],16)
                            << QString::number(myVal.data[3],16)
                            << QString::number(myVal.data[4],16)
                            << QString::number(myVal.data[5],16)
                            << QString::number(myVal.data[6],16)
                            << QString::number(myVal.data[7],16);
#endif
    }
    else
    {
       qDebug()<<"读取内容解析失败";
    }
    // 因为都在MainWindow 里定义，所以这里可以直接调用函数接口
    // 而不需使用connect

    myQwidgt->setWindowTitle("Can_Monitor       " + myVal.timestamp.toString("yyyy-MM-dd HH:mm:ss.zzz"));
    ZCAN_Receive_Data  logdat;
    logdat.timestamp = myVal.timestamp.toMSecsSinceEpoch();
    logdat.frame.can_id = myVal.frameId + 0x80000000;
    logdat.frame.can_dlc = 8;
    memcpy(logdat.frame.data,myVal.data,8);

    showCanDat(logdat,0,nullptr,ql_temp,myVal.timestamp.toString("yyyy-MM-dd HH:mm:ss.zzz"));
    showCanDat(logdat,0,nullptr,Lab_ql_temp,myVal.timestamp.toString("yyyy-MM-dd HH:mm:ss.zzz"));
}

// 复位显示值告警
void MainWindow::on_send_disreset(int32_t index)
{
    myLE_txt[index]->setStyleSheet("font: 12pt; "
                               "color: rgb(0, 0, 0);"
                                   );
}

// 显示数据趋势图

void MainWindow::on_send_GUI(int32_t index)
{
    QString textLine[4000];
    logFileFullPath = logPath2 + QCom_log->currentText();
     QFile logfile(logFileFullPath); //检查文件

     if (!logfile.open(QIODevice::ReadOnly | QIODevice::Text))
     {
         qDebug() << "打开log文件失败";
         return ;
     }
     QTextStream in(&logfile);

     QString line;
     S_LogEntry myVal;
     uint32_t num = 0;

     myguiData.clear();
     myguiData.reserve(68400);
     gui_time.clear();
     gui_time.reserve(68400);

     while (!in.atEnd())
     {
         num++;
         line = in.readLine();
         parseLogLine(line, myVal);
         if(ql_temp[index].frame_id == myVal.frameId)
         {
             uint32_t hander = ( (uint16_t)myVal.data[0] << 8 ) + myVal.data[1];
             uint32_t dat = 0;
             double    fdat = 0;
             if(ql_temp[index].header == hander)
             {
                 switch (ql_temp[index].data_len)
                 {
                    case 0x01:
                           dat = myVal.data[ql_temp[index].data_ptr];
                      break;

                    case 0x02:
                           dat = ((uint32_t)(myVal.data[ql_temp[index].data_ptr])<< 8)
                                +  myVal.data[ql_temp[index].data_ptr+1];
                     break;

                    case 0x03:
                           dat =  ((uint32_t)(myVal.data[ql_temp[index].data_ptr])<< 16)
                                 + ((uint32_t)(myVal.data[ql_temp[index].data_ptr+1])<< 8)
                                 +  myVal.data[ql_temp[index].data_ptr+2];
                     break;

                    case 0x04:
                           dat =   ((uint32_t)(myVal.data[ql_temp[index].data_ptr])<< 24)
                                 + ((uint32_t)(myVal.data[ql_temp[index].data_ptr+1])<< 16)
                                 + ((uint32_t)(myVal.data[ql_temp[index].data_ptr+2])<< 8)
                                 +  myVal.data[ql_temp[index].data_ptr+3];

                    default: break;
                 }
                 dat = dat - ql_temp[index].offset;
                 fdat = (double) dat / ql_temp[index].dis_real_coff;

                 gui_time.append(myVal.timestamp);
                 myguiData.append(fdat);
             }
         }
     }
     qDebug()<<"size:"<<myguiData.size()<<gui_time.size();

     static PlotDialog *plotDialog = nullptr; // 静态变量，用于管理实例
      // 删除之前的实例
      if (plotDialog)
      {
          plotDialog->deleteLater(); // 安全删除
          plotDialog = nullptr;
      }
      // 创建新实例
      plotDialog = new PlotDialog();
      plotDialog->setWindowTitle(ql_temp[index].var_name);
      plotDialog->show(); // 非模态显示
}




void MainWindow::make_top_gui()
{

    myQwidgt->setLayout(top_layout);
    top_layout->addLayout(top_hlayout);

    #ifdef  ONLY_QSCROLLAREA
    v1_scrollArea->setWidgetResizable(true);
    v1_scrollArea->setWidget(sub1Qwidgt);
    #else
    // 使滚动区域可以调整大小
    v1_scrollArea->setWidgetResizable(true);
    v2_scrollArea->setWidgetResizable(true);
    v3_scrollArea->setWidgetResizable(true);
    // 将布局容器设置为QScrollArea的子控件
    v1_scrollArea->setWidget(sub1Qwidgt);
    v2_scrollArea->setWidget(sub2Qwidgt);
    v2_scrollArea->setWidget(sub3Qwidgt);
    #endif

  #ifdef  ONLY_QSCROLLAREA
     top_layout->addWidget(v1_scrollArea);
  #else
    v1_layout->addWidget(v1_scrollArea);
    v2_layout->addWidget(v2_scrollArea);
    v3_layout->addWidget(v3_scrollArea);
  #endif


    //#########################   这里放置标题  #########################
    QLab_CANDEV->setStyleSheet("font: 12pt ;");
    top_hlayout->addWidget(QLab_CANDEV);


    QCom_CANDEV->addItem("ZLG_USBCAN");
    QCom_CANDEV->addItem("GY8507");
    QCom_CANDEV->addItem("RS232/485");
    top_hlayout->addWidget(QCom_CANDEV);

    QCom_CANCHsel->addItem("0");
    QCom_CANCHsel->addItem("1");
    top_hlayout->addWidget(QCom_CANCHsel);

    QLab_BaudRate->setStyleSheet("font: 12pt ;");
    top_hlayout->addWidget(QLab_BaudRate);


    QCom_Baud->addItem("50K-2400");
    QCom_Baud->addItem("100K-4800");
    QCom_Baud->addItem("125K-9600");
    QCom_Baud->addItem("250K-19200");
    QCom_Baud->addItem("500K-115200");
    QCom_Baud->addItem("1000K-921600");
    top_hlayout->addWidget(QCom_Baud);

    QPbtn_OPDEV->setStyleSheet("font: 12pt ;");
    top_hlayout->addWidget(QPbtn_OPDEV);
    connect(QPbtn_OPDEV,&QPushButton :: clicked,this,&MainWindow::on_BTN_OpenDev);

    QLab_Config->setStyleSheet("font: 12pt ;");
    top_hlayout->addWidget(QLab_Config);
    top_hlayout->addWidget(QCom_Config);

    QPbtn_LoadConfig->setStyleSheet("font: 12pt ;");
    top_hlayout->addWidget(QPbtn_LoadConfig);
    connect(QPbtn_LoadConfig,&CustomButton :: send_loadAction,this,&MainWindow::on_BTN_LoadConfig);
    QPbtn_LoadConfig->setContextMenuPolicy(Qt::CustomContextMenu);
    connect(QPbtn_LoadConfig, &CustomButton::customContextMenuRequested,
            this, &MainWindow::showContextMenu);

    connect(QCom_CANDEV,&QComboBox::currentTextChanged,
             this,&MainWindow::on_QCom_CANDEV_change);

    top_layout->addLayout(main_hlayout);
}

void MainWindow::scan_configfile(QString ScanPath)
{
    QDir dir(ScanPath);

    if(!dir.exists())
    {
        //目录不存在，处理错误
        return;
    }

    QStringList  nameFilters;
    nameFilters << "*" ; //只显示文件夹
    QStringList entries = dir.entryList(nameFilters ,QDir::Dirs|QDir::NoDotAndDotDot,QDir::Name);

    QCom_Config->clear();
    for (const QString &entry :entries )
    {
        QCom_Config->addItem(entry);
    }
}

void MainWindow::scan_logfile(QString ScanPath)
{
    QDir dir(ScanPath);


    if(!dir.exists())
    {
        // 目录不存在，处理错误
        return;
    }

    QStringList nameFilters;
    nameFilters << "*.log"; // 只显示.log文件

    // 获取文件列表，排除 . 和 .. 目录，按名称排序
    QStringList entries = dir.entryList(nameFilters, QDir::Files | QDir::NoDotAndDotDot, QDir::Name);
    QCom_log->clear();
    for (const QString &entry : entries)
    {
        // 假设 QCom_log 是一个 QListWidget 或者类似的可以添加项目的控件
        QCom_log->addItem(entry);
    }
}


// 加载历史事件
void MainWindow::on_HisEvent()
{
    logFileFullPath = logPath2 + QCom_log->currentText();
     QFile logfile(logFileFullPath); //检查文件
     if (!logfile.open(QIODevice::ReadOnly | QIODevice::Text))
     {
         qDebug() << "打开log文件失败";
         return ;
     }
     QTextStream in(&logfile);

     QString line;
     S_LogEntry myVal;
     uint32_t num = 0;

     while (!in.atEnd())
     {
         num++;
         line = in.readLine();
         bool isDat =  parseLogLine(line, myVal);
         if (!isDat)
         {
            qDebug()<<"读取内容解析失败";
         }
         ZCAN_Receive_Data  logdat;
         logdat.frame.can_id = myVal.frameId + 0x80000000;
         logdat.frame.can_dlc = 8;
         memcpy(logdat.frame.data,myVal.data,8);

         enWindDispalyMode = WIND_HISTORY_EVENT;
         showCanDat(logdat,0,nullptr,ql_temp,myVal.timestamp.toString("yyyy-MM-dd HH:mm:ss.zzz"));
         showCanDat(logdat,0,nullptr,Lab_ql_temp,myVal.timestamp.toString("yyyy-MM-dd HH:mm:ss.zzz"));
         if(Realtime_flag == 0)
         {
            enWindDispalyMode = WIND_LOG_PALY;
         }
         else
         {
            enWindDispalyMode = WIND_REALY_TIME;
         }
     }
}



bool MainWindow::openSerialPort(const QString &portName, int baudRate)
{
    m_port->setPortName(portName);
    m_port->setBaudRate(static_cast<QSerialPort::BaudRate>(baudRate));
    m_port->setDataBits(QSerialPort::Data8);
    m_port->setParity(QSerialPort::NoParity);
    m_port->setStopBits(QSerialPort::OneStop);
    m_port->setFlowControl(QSerialPort::NoFlowControl);
    return m_port->open(QIODevice::ReadWrite);
}

void MainWindow::closeSerialPort()
{
    if (m_port->isOpen())
    {
        m_port->close();
    }
}



void MainWindow::sendCommand(const char *data, int size)
{
    if (m_port->isOpen())
    {
        m_port->write(data, size);
    }
}


void MainWindow::on_QCom_CANDEV_change()
{
   qDebug()<<QCom_CANDEV->currentIndex();
   if(QCom_CANDEV->currentIndex() == 2)
   {
       QCom_CANCHsel->clear();
       foreach (const QSerialPortInfo &info, QSerialPortInfo::availablePorts())
       {
           QCom_CANCHsel->addItem(info.portName() + " " + info.description());
       }
   }
   else
   {
        QCom_CANCHsel->clear();
        QCom_CANCHsel->addItem("0");
        QCom_CANCHsel->addItem("1");
   }
}


void MainWindow::slot_update_tx_timer()
{
   QTIM_tx.stop();
}


void MainWindow::slot_update_rx_timer()
{
     QTIM_rx.stop();

     QByteArray SCIDate;
     m_port->waitForReadyRead(1);
     if(m_port->bytesAvailable())
     {
         SCIDate =  m_port->readAll();//.toHex();
         m_port->flush();
     }
     if(SCIDate.length() != 0)
     {
       Mydate = (uint8_t *)SCIDate.data();

       QString txtStr = "串口收到数据: ";
       QString lenStr = "len: "+ QString::number(SCIDate.length());
       QString DatStr = "dat(hex): ";
       QString subStr;
       for (int i=0;i < SCIDate.length();i++)
       {
           subStr += QString::number(Mydate[i],16).toUpper().rightJustified(2,'0',true)+" ";
       }

       qDebug()<<txtStr<<lenStr<<DatStr<<subStr;

     }
}

void MainWindow::onSerialPortReadyRead()
{
    // 接收到数据启动定时器
    // 在定时器的槽函数里处理数据
    QTIM_rx.start(5);
    // 这里可以进行一些耗时较少的操作
}




